import os
import binascii
from iroha import IrohaCrypto
from iroha import Iroha, IrohaGrpc
import sys
from Crypto.Hash import keccak
import integration_helpers

if sys.version_info[0] < 3:
    raise Exception("Python 3 or a more recent version is required.")

# Here is the information about the environment and admin account information:
IROHA_HOST_ADDR = os.getenv("IROHA_HOST_ADDR", "127.0.0.1")
IROHA_PORT = os.getenv("IROHA_PORT", "50051")
ADMIN_ACCOUNT_ID = os.getenv("ADMIN_ACCOUNT_ID", "admin@test")
ADMIN_PRIVATE_KEY = os.getenv(
    "ADMIN_PRIVATE_KEY",
    "f101537e319568c765b2cc89698325604991dca57b9716b58016b253506cab70",
)

iroha = Iroha(ADMIN_ACCOUNT_ID)
net = IrohaGrpc("{}:{}".format(IROHA_HOST_ADDR, IROHA_PORT))

test_private_key = IrohaCrypto.private_key()
test_public_key = IrohaCrypto.derive_public_key(test_private_key).decode("utf-8")


@integration_helpers.trace
def create_contract():
    bytecode = "608060405234801561001057600080fd5b5073a6abc17819738299b3b2c1ce46d55c74f04e290c6000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550610fd4806100746000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632c74aaaf1461005c57806395256b2c1461008c578063bc53c0c4146100bc578063d4e804ab146100ec578063e048232a1461010a575b600080fd5b61007660048036038101906100719190610896565b61013a565b6040516100839190610bfa565b60405180910390f35b6100a660048036038101906100a19190610999565b6102a9565b6040516100b39190610bfa565b60405180910390f35b6100d660048036038101906100d19190610902565b610484565b6040516100e39190610bfa565b60405180910390f35b6100f461064e565b6040516101019190610bdf565b60405180910390f35b610124600480360381019061011f9190610896565b610672565b6040516101319190610bfa565b60405180910390f35b606060008383604051602401610151929190610c3e565b6040516020818303038152906040527f260b5d52000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16836040516102189190610bb1565b600060405180830381855af49150503d8060008114610253576040519150601f19603f3d011682016040523d82523d6000602084013e610258565b606091505b50915091508161029d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161029490610d57565b60405180910390fd5b80935050505092915050565b6060600086868686866040516024016102c6959493929190610cc1565b6040516020818303038152906040527f95256b2c000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168360405161038d9190610bb1565b600060405180830381855af49150503d80600081146103c8576040519150601f19603f3d011682016040523d82523d6000602084013e6103cd565b606091505b509150915081610412576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161040990610d37565b60405180910390fd5b876040516104209190610bc8565b6040518091039020896040516104369190610bc8565b60405180910390207f6a739057159b3f3e2efcba00d44b0fa47de56972ed8776a2da7682bcf7c67de18760405161046d9190610c1c565b60405180910390a380935050505095945050505050565b6060600084848460405160240161049d93929190610c75565b6040516020818303038152906040527fbc53c0c4000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16836040516105649190610bb1565b600060405180830381855af49150503d806000811461059f576040519150601f19603f3d011682016040523d82523d6000602084013e6105a4565b606091505b5091509150816105e9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016105e090610d37565b60405180910390fd5b856040516105f79190610bc8565b60405180910390208760405161060d9190610bc8565b60405180910390207fb4086b7a9e5eac405225b6c630a4147f0a8dcb4af3583733b10db7b91ad21ffd60405160405180910390a38093505050509392505050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b606060008383604051602401610689929190610c3e565b6040516020818303038152906040527fe048232a000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008060008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16836040516107509190610bb1565b600060405180830381855af49150503d806000811461078b576040519150601f19603f3d011682016040523d82523d6000602084013e610790565b606091505b5091509150816107d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107cc90610d37565b60405180910390fd5b856040516107e39190610bc8565b60405180910390207fd8ea495c3185a632d25d8ccc5c355aeb4058bfaaaee8647c075dc5c1ce62914c8660405161081a9190610c1c565b60405180910390a280935050505092915050565b600061084161083c84610d9c565b610d77565b90508281526020810184848401111561085957600080fd5b610864848285610e4d565b509392505050565b600082601f83011261087d57600080fd5b813561088d84826020860161082e565b91505092915050565b600080604083850312156108a957600080fd5b600083013567ffffffffffffffff8111156108c357600080fd5b6108cf8582860161086c565b925050602083013567ffffffffffffffff8111156108ec57600080fd5b6108f88582860161086c565b9150509250929050565b60008060006060848603121561091757600080fd5b600084013567ffffffffffffffff81111561093157600080fd5b61093d8682870161086c565b935050602084013567ffffffffffffffff81111561095a57600080fd5b6109668682870161086c565b925050604084013567ffffffffffffffff81111561098357600080fd5b61098f8682870161086c565b9150509250925092565b600080600080600060a086880312156109b157600080fd5b600086013567ffffffffffffffff8111156109cb57600080fd5b6109d78882890161086c565b955050602086013567ffffffffffffffff8111156109f457600080fd5b610a008882890161086c565b945050604086013567ffffffffffffffff811115610a1d57600080fd5b610a298882890161086c565b935050606086013567ffffffffffffffff811115610a4657600080fd5b610a528882890161086c565b925050608086013567ffffffffffffffff811115610a6f57600080fd5b610a7b8882890161086c565b9150509295509295909350565b610a9181610e1b565b82525050565b6000610aa282610dcd565b610aac8185610de3565b9350610abc818560208601610e5c565b610ac581610eef565b840191505092915050565b6000610adb82610dcd565b610ae58185610df4565b9350610af5818560208601610e5c565b80840191505092915050565b6000610b0c82610dd8565b610b168185610dff565b9350610b26818560208601610e5c565b610b2f81610eef565b840191505092915050565b6000610b4582610dd8565b610b4f8185610e10565b9350610b5f818560208601610e5c565b80840191505092915050565b6000610b78602783610dff565b9150610b8382610f00565b604082019050919050565b6000610b9b602883610dff565b9150610ba682610f4f565b604082019050919050565b6000610bbd8284610ad0565b915081905092915050565b6000610bd48284610b3a565b915081905092915050565b6000602082019050610bf46000830184610a88565b92915050565b60006020820190508181036000830152610c148184610a97565b905092915050565b60006020820190508181036000830152610c368184610b01565b905092915050565b60006040820190508181036000830152610c588185610b01565b90508181036020830152610c6c8184610b01565b90509392505050565b60006060820190508181036000830152610c8f8186610b01565b90508181036020830152610ca38185610b01565b90508181036040830152610cb78184610b01565b9050949350505050565b600060a0820190508181036000830152610cdb8188610b01565b90508181036020830152610cef8187610b01565b90508181036040830152610d038186610b01565b90508181036060830152610d178185610b01565b90508181036080830152610d2b8184610b01565b90509695505050505050565b60006020820190508181036000830152610d5081610b6b565b9050919050565b60006020820190508181036000830152610d7081610b8e565b9050919050565b6000610d81610d92565b9050610d8d8282610e8f565b919050565b6000604051905090565b600067ffffffffffffffff821115610db757610db6610ec0565b5b610dc082610eef565b9050602081019050919050565b600081519050919050565b600081519050919050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b6000610e2682610e2d565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b82818337600083830152505050565b60005b83811015610e7a578082015181840152602081019050610e5f565b83811115610e89576000848401525b50505050565b610e9882610eef565b810181811067ffffffffffffffff82111715610eb757610eb6610ec0565b5b80604052505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000601f19601f8301169050919050565b7f4572726f722063616c6c696e67207365727669636520636f6e7472616374206660008201527f756e6374696f6e00000000000000000000000000000000000000000000000000602082015250565b7f4572726f722063616c6c696e67207365727669636520636f6e7472616374206660008201527f756e6374696f6e2000000000000000000000000000000000000000000000000060208201525056fea26469706673582212204e4b30bb374a8e823a8628a2ad17e7485b253d4844672db1260c0c68e00de93164736f6c63430008040033"
    """Bytecode was generated using remix editor  https://remix.ethereum.org/ from file iroha.sol. """
    tx = iroha.transaction(
        [iroha.command("CallEngine", caller=ADMIN_ACCOUNT_ID, input=bytecode)]
    )
    IrohaCrypto.sign_transaction(tx, ADMIN_PRIVATE_KEY)
    net.send_tx(tx)
    hex_hash = binascii.hexlify(IrohaCrypto.hash(tx))
    for status in net.tx_status_stream(tx):
        print(status)
    return hex_hash


@integration_helpers.trace
def add_asset_quantity(address):
    params = integration_helpers.get_first_four_bytes_of_keccak(
        b"addAssetQuantity(string,string)"
    )
    no_of_param = 2
    for x in range(no_of_param):
        params = params + integration_helpers.left_padded_address_of_param(
            x, no_of_param
        )
    params = params + integration_helpers.argument_encoding("coin#domain")  # asset id
    params = params + integration_helpers.argument_encoding("500")  # amount of asset
    tx = iroha.transaction(
        [
            iroha.command(
                "CallEngine", caller=ADMIN_ACCOUNT_ID, callee=address, input=params
            )
        ]
    )
    IrohaCrypto.sign_transaction(tx, ADMIN_PRIVATE_KEY)
    response = net.send_tx(tx)
    for status in net.tx_status_stream(tx):
        print(status)


@integration_helpers.trace
def create_account(address):
    params = integration_helpers.get_first_four_bytes_of_keccak(
        b"createAccount(string,string,string)"
    )
    no_of_param = 3
    for x in range(no_of_param):
        params = params + integration_helpers.left_padded_address_of_param(
            x, no_of_param
        )
    params = params + integration_helpers.argument_encoding(
        "test4"
    )  # source account id
    params = params + integration_helpers.argument_encoding("test")  # domain id
    params = params + integration_helpers.argument_encoding(test_public_key)  #  key
    tx = iroha.transaction(
        [
            iroha.command(
                "CallEngine", caller=ADMIN_ACCOUNT_ID, callee=address, input=params
            )
        ]
    )
    IrohaCrypto.sign_transaction(tx, ADMIN_PRIVATE_KEY)
    response = net.send_tx(tx)
    for status in net.tx_status_stream(tx):
        print(status)
    hex_hash = binascii.hexlify(IrohaCrypto.hash(tx))
    return hex_hash


@integration_helpers.trace
def transfer(address):
    params = integration_helpers.get_first_four_bytes_of_keccak(
        b"transferAsset(string,string,string,string,string)"
    )
    no_of_param = 5
    for x in range(no_of_param):
        params = params + integration_helpers.left_padded_address_of_param(
            x, no_of_param
        )
    params = params + integration_helpers.argument_encoding(
        ADMIN_ACCOUNT_ID
    )  # source account
    params = params + integration_helpers.argument_encoding(
        "userone@domain"
    )  # destination account
    params = params + integration_helpers.argument_encoding("coin#domain")  # asset id
    params = params + integration_helpers.argument_encoding("transfer")  # description
    params = params + integration_helpers.argument_encoding("100")  # amount of asset
    tx = iroha.transaction(
        [
            iroha.command(
                "CallEngine", caller=ADMIN_ACCOUNT_ID, callee=address, input=params
            )
        ]
    )
    IrohaCrypto.sign_transaction(tx, ADMIN_PRIVATE_KEY)
    response = net.send_tx(tx)
    for status in net.tx_status_stream(tx):
        print(status)


@integration_helpers.trace
def balance(address):
    params = integration_helpers.get_first_four_bytes_of_keccak(
        b"queryBalance(string,string)"
    )
    no_of_param = 2
    for x in range(no_of_param):
        params = params + integration_helpers.left_padded_address_of_param(
            x, no_of_param
        )
    params = params + integration_helpers.argument_encoding(
        ADMIN_ACCOUNT_ID
    )  # account id
    params = params + integration_helpers.argument_encoding("coin#domain")  # asset id
    tx = iroha.transaction(
        [
            iroha.command(
                "CallEngine", caller=ADMIN_ACCOUNT_ID, callee=address, input=params
            )
        ]
    )
    IrohaCrypto.sign_transaction(tx, ADMIN_PRIVATE_KEY)
    response = net.send_tx(tx)
    for status in net.tx_status_stream(tx):
        print(status)
    hex_hash = binascii.hexlify(IrohaCrypto.hash(tx))
    return hex_hash


hash = create_contract()
address = integration_helpers.get_engine_receipts_address(hash)
hash = balance(address)
integration_helpers.get_engine_receipts_result(hash)
add_asset_quantity(address)
hash = balance(address)
integration_helpers.get_engine_receipts_result(hash)
transfer(address)
hash = balance(address)
integration_helpers.get_engine_receipts_result(hash)
create_account(address)

print("done")
